﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace MyValidationLibrary
{
	public sealed class MyValidatorManager
	{
		private Object m_obj;
		List<string> m_Errors;
		private bool found = false;

		public MyValidatorManager()
		{
			m_obj = null;
			m_Errors = new List<string>();
		}

		public MyValidatorManager(object obj)
		{
			m_obj = obj;
			m_Errors = new List<string>();
		}

		public List<string> Errors
		{
			get
			{
				return m_Errors;
			}
		}

		public bool Validate()
		{
			if (m_obj == null)
				throw new ArgumentException("obj cannot be null");

			m_Errors.Clear();

			Type type = m_obj.GetType();
			foreach (PropertyInfo pi in type.GetProperties())
			{
				object[] attr = pi.GetCustomAttributes(false);
				foreach (object attribute in attr)
				{
					switch (attribute.GetType().Name)
					{
						case "DefaultValueAttribute":
							object def = pi.GetValue(m_obj, null);
							SetDefaultValue(m_obj, pi, (DefaultValueAttribute)attribute);
							break;

						case "StringLenghtAttribute":
							string data = pi.GetValue(m_obj, null) as string;
							if (data.Length > (attribute as StringLenghtAttribute).Lenght)
							{
								AddToMessages(pi, attribute);
								found = true;
							}
							break;

						case "RangeAttribute":
							object range = pi.GetValue(m_obj, null);
							if ((int)range > (attribute as RangeAttribute).Max || (int)range < (attribute as RangeAttribute).Min)
							{
								AddToMessages(pi, attribute);
								found = true;
							}
							break;

						case "RequiredAttribute":

							object required = pi.GetValue(m_obj, null);
							if (required == null && (attribute as RequiredAttribute).Required)
							{
								AddToMessages(pi, attribute);
								found = true;
							}

							break;

						case "RegexValidationAttribute":
							string output = (attribute as RegexValidationAttribute).IsValid(pi, m_obj);
							if (!string.IsNullOrEmpty(output))
							{
								this.AddToMessages(pi, attribute);
							}
							break;

						default:

							break;
					}
				}
			}

			return !found;
		}

		private void AddToMessages(PropertyInfo pi, object attribute)
		{
			m_Errors.Add(string.Format("{0} - {1}", pi.Name, (attribute as BaseValidationAttribute).ErrorMessage));
		}

		private void SetDefaultValue(object instance, PropertyInfo pi, DefaultValueAttribute att)
		{
			pi.SetValue(instance, att.DefaultValue, null);
		}

	}

	public class BusinessExample
	{
		[StringLenght(4, "Cannot be more than 4")]
		public string Data
		{
			get;
			set;
		}

		[StringLenght(12, "Must be less than 12")]
		public string Data2
		{
			get;
			set;
		}

		[Range(16, 60, "Age must be less than 60 but more 16")]
		public int Age
		{
			get;
			set;
		}

		[DefaultValue("Defaut")]
		public string Information
		{
			get;
			set;
		}

		[RequiredAttribute("This propersty cannot be null")]
		public object Container
		{
			get;
			set;
		}

		[RegexValidation(@"\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*","Input is incorretc")]
		public string Email
		{
			get;
			set;
		}
	}
}
